from interface.widget import Page, scale, scale_factor, YScrollableContainer, max_children_y_core
from tkinter import ttk
import tkinter
from interface.widget.chat import Message, FileMessage, ImageMessage
from utils import memory
import time
import threading
from utils.network import request
import re
import json


class ChatPage(Page):

    def __init__(self, master, account):
        Page.__init__(self, master)
        self.account = account
        self.message_y = 10
        self.message_widgets = []
        self.on_adjust_message_height = False
        self.history_container = None
        self.history_box = None
        self.displayed_messages = []
        self.thread_continue = True

    def content(self, master):
        ttk.Style().configure('ChatPage.TitleBox.TLabel', background='#cccccc', anchor='center')
        title_box = ttk.Label(master, text='{} ({})'
                              .format(memory.users[self.account]['username'],self.account),
                              style='ChatPage.TitleBox.TLabel')
        title_box.place(**scale(relx=0, rely=0, relwidth=1, height=30))

        history_container = YScrollableContainer(master)
        history_container.relx = 0
        history_container.rely = 0
        history_container.y = 30
        history_container.relwidth = 1
        history_container.relheight = 0.6
        history_container.height = -30
        history_container.display()
        self.history_container = history_container

        history_box = ttk.Frame(history_container.inner.tkw)
        history_box.place(**scale(relx=0, x=10, rely=0, relwidth=1, width=-20))
        self.history_box = history_box

        ttk.Style().configure('ChatPage.ButtonBox.TFrame', background='#cccccc')
        button_box = ttk.Frame(master, style='ChatPage.ButtonBox.TFrame')
        button_box.place(**scale(relx=0, rely=0.6, relwidth=1, height=40))

        message_entry = tkinter.Text(master)
        message_entry.place(**scale(relx=0, rely=0.6, y=40, relwidth=1, relheight=0.4, height=-40))

        def send_button_method():
            text = message_entry.get('1.0', tkinter.END)
            if text[-1] == '\n':
                text = text[: -1]
            res = request('/message/send', {
                'recipients': [self.account],
                'text': text
            })
            for message in res['messages']:
                memory.add_message(message)
            message_entry.delete('1.0', tkinter.END)

        send_button = ttk.Button(button_box, text='发送', command=send_button_method)
        send_button.place(**scale(relx=1, x=-100, y=5, width=80, height=30))

        self.tkw.bind('<Configure>', lambda e: self.adjust_message_height())

        self.start_update_messages_background_thread()

    def add_message(self, message):
        # 调整高度时不能添加消息
        while self.on_adjust_message_height:
            time.sleep(0.1)
        is_file_rtn = is_file_message(message['text'])
        is_image_rtn = is_image_message(message['text'])
        if is_file_rtn:  # File message.
            message_widget = FileMessage(self.history_box, message, is_file_rtn)
        elif is_image_rtn:  # Image message.
            message_widget = ImageMessage(self.history_box, message, is_image_rtn)
        else:
            message_widget = Message(self.history_box, message)
        message_widget.y = self.message_y
        message_widget.display()
        self.message_y += message_widget.adjust_height() / scale_factor + 12
        self.message_widgets.append(message_widget)
        self.history_box.place(height=max_children_y_core(self.history_box))
        self.history_container.update()
        self.history_container.to_bottom()

    def adjust_message_height(self):
        self.on_adjust_message_height = True
        self.message_y = 10
        for message_widget in self.message_widgets:
            message_widget.y = self.message_y
            message_widget.place()
            self.message_y += message_widget.adjust_height() / scale_factor + 12
        self.history_box.place(height=max_children_y_core(self.history_box))
        self.history_container.update()
        self.on_adjust_message_height = False

    def update_messages(self):
        for message in memory.users[self.account]['messages']:
            if message not in self.displayed_messages:
                self.add_message(message)
                self.displayed_messages.append(message)

    def start_update_messages_background_thread(self):
        def run():
            while self.thread_continue:
                self.update_messages()
                time.sleep(0.5)
        threading.Thread(target=run, daemon=True).start()

    def destroy(self):
        Page.destroy(self)
        self.thread_continue = False


def is_file_message(message):
    rtn = re.match('<file>.*</file>', message)
    if rtn:
        return json.loads(rtn.group()[6: -7])


def is_image_message(message):
    rtn = re.match('<image>.*</image>', message)
    if rtn:
        return json.loads(rtn.group()[7: -8])
